home *** CD-ROM | disk | FTP | other *** search
/ Aminet 51 / Aminet 51 (2002)(GTI - Schatztruhe)[!][Oct 2002].iso / Aminet / util / arc / xadmasterdev.lha / xad / Sources / tools / xadUnDisk.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-08-20  |  21.2 KB  |  732 lines

  1. #define NAME         "xadUnDisk"
  2. #define DISTRIBUTION "(Freeware) "
  3. #define REVISION     "14"
  4. #define DATE         "06.08.2002"
  5.  
  6. /* Programmheader
  7.  
  8.         Name:           xadUnDisk
  9.         Author:         SDI
  10.         Distribution:   Freeware
  11.         Description:    dearchives disk archives
  12.         Compileropts:   -
  13.         Linkeropts:     -gsi -l amiga
  14.  
  15.  1.0   18.11.98 : first version
  16.  1.1   23.12.98 : added support for FILEDESCRIPT
  17.  1.2   04.02.99 : added file corrupt message, new InfoText system and SAVETEXTS
  18.  1.3   16.02.99 : bug fix in report hook
  19.  1.4   28.02.99 : little bug fix in chunk hook
  20.  1.5   15.09.99 : added insert disk question
  21.  1.6   20.02.00 : added FORMAT keyword and ADF to disk
  22.  1.7   19.03.00 : bug fix
  23.  1.8   12.04.00 : image question only, if XADERR_FILETYPE
  24.  1.9   07.07.00 : added NOASKINSERT keyword
  25.  1.10  21.08.00 : now uses xadGetHookAccess instead of own image copy
  26.  1.11  11.11.00 : fixed Enforcer hit, added USESECTORLABELS
  27.  1.12  02.12.01 : added disk-input support
  28.  1.13  19.01.02 : fixed disk-input handling and DIMG handling
  29.  1.14  06.08.02 : added diskarc-device input, added pattern support
  30. */
  31.  
  32. #include <proto/xadmaster.h>
  33. #include <proto/exec.h>
  34. #include <proto/dos.h>
  35. #include <proto/utility.h>
  36. #include <exec/memory.h>
  37. #include <devices/trackdisk.h>
  38. #include <dos/dosasl.h>
  39. #include <dos/filehandler.h>
  40. #include <utility/hooks.h>
  41. #include "SDI_version.h"
  42. #include "SDI_compiler.h"
  43. #define SDI_TO_ANSI
  44. #include "SDI_ASM_STD_protos.h"
  45.  
  46. struct xadMasterBase *   xadMasterBase = 0;
  47. struct DosLibrary *      DOSBase = 0;
  48. struct ExecBase *        SysBase  = 0;
  49.  
  50. #define PARAM   "FROM/A,TO,LOWCYL/N,HIGHCYL/N,ENTRY/N,PASSWORD,SAVETEXTS/K," \
  51.                 "NE=NOEXTERN/S,INFO=LIST/S,SHOWTEXTS/S,OW=OVERWRITE/S," \
  52.                 "IG=IGNOREGEOMETRY/S,FORMAT/S,DIMG=DISKIMAGE/S,NAI=NOASKINSERT/S," \
  53.                 "USL=USESECTORLABELS/S"
  54.  
  55. struct Args {
  56.   STRPTR   from;
  57.   STRPTR   to;
  58.   LONG *   lowcyl;
  59.   LONG *   highcyl;
  60.   LONG *   entry;
  61.   STRPTR   password;
  62.   STRPTR   savetexts;
  63.   ULONG    noextern;
  64.   ULONG    info;
  65.   ULONG    showtexts;
  66.   ULONG    overwrite;
  67.   ULONG    ignoregeometry;
  68.   ULONG    format;
  69.   ULONG    diskimage;
  70.   ULONG    noaskinsert;
  71.   ULONG    usesectorlabels;
  72. };
  73.  
  74. ASM(ULONG) SAVEDS progrhook(REG(a0, struct Hook *),
  75.   REG(a1, struct xadProgressInfo *));
  76. static struct Hook prhook = {{0,0},(ULONG (*)()) progrhook, 0, 0};
  77. static void ShowTexts(struct xadTextInfo *ti);
  78. static void SaveTexts(struct xadTextInfo *ti, STRPTR name);
  79. static LONG WriteDisk(struct Args *, struct TagItem *);
  80. static void FreeMyTags(struct TagItem *ti);
  81. static struct TagItem *GetMyTags(STRPTR name, LONG *reserr);
  82. static LONG AskInsertDisk(STRPTR);
  83.  
  84. ULONG start(void)
  85. {
  86.   ULONG ret = RETURN_FAIL;
  87.   struct DosLibrary *dosbase;
  88.  
  89.   SysBase = (*((struct ExecBase **) 4));
  90.   { /* test for WB and reply startup-message */
  91.     struct Process *task;
  92.     if(!(task = (struct Process *) FindTask(0))->pr_CLI)
  93.     {
  94.       WaitPort(&task->pr_MsgPort);
  95.       Forbid();
  96.       ReplyMsg(GetMsg(&task->pr_MsgPort));
  97.       return RETURN_FAIL;
  98.     }
  99.   }
  100.  
  101.   if((dosbase = (struct DosLibrary *) OpenLibrary("dos.library", 37)))
  102.   {
  103.     LONG err = 0;
  104.     struct xadMasterBase *xadmasterbase;
  105.  
  106.     DOSBase = dosbase;
  107.     if((xadmasterbase = (struct xadMasterBase *) OpenLibrary("xadmaster.library", 11)))
  108.     {
  109.       LONG def = 1;
  110.       struct Args args;
  111.       struct RDArgs *rda;
  112.       
  113.       memset(&args, 0 , sizeof(struct Args));
  114.       args.entry = &def;
  115.  
  116.       xadMasterBase = xadmasterbase;
  117.       if((rda = ReadArgs(PARAM, (LONG *) &args, 0)))
  118.       {
  119.         if(args.to || args.info)
  120.         {
  121.           struct xadArchiveInfo *ai;
  122.           struct TagItem *ti;
  123.  
  124.           if(ti = GetMyTags(args.from, &err))
  125.           {
  126.             LONG doit = 0;
  127.  
  128.             if(args.diskimage)
  129.             {
  130.               ret = 0;
  131.               err = WriteDisk(&args, ti);
  132.             }
  133.             else if(ti[0].ti_Tag == XAD_INDEVICE)
  134.             {
  135.               LONG r;
  136.  
  137.               ret = 0;
  138.               Printf("Device input. Press <I> to read and write disk as image: ");
  139.               Flush(Output());
  140.               SetMode(Input(), TRUE);
  141.               r = FGetC(Input());
  142.               SetMode(Input(), FALSE);
  143.               if(r == 'i' || r == 'I')
  144.                 err = WriteDisk(&args, ti);
  145.               else
  146.               {
  147.                 Printf("\n"); doit = 1;
  148.               }
  149.             }
  150.             else
  151.               doit = 1;
  152.  
  153.             if(doit && (ai = (struct xadArchiveInfo *)
  154.             xadAllocObjectA(XADOBJ_ARCHIVEINFO, 0)))
  155.             {
  156.               if(!err && !(err = xadGetInfo(ai, XAD_NOEXTERN, args.noextern,
  157.               args.password ? XAD_PASSWORD : TAG_IGNORE, args.password,
  158.               TAG_MORE, ti)))
  159.               {
  160.                 if(ai->xai_Flags & XADAIF_FILECORRUPT)
  161.                   Printf("!!! The archive file has some corrupt data. !!!\n");
  162.                 if(args.info)
  163.                 {
  164.                   struct xadDiskInfo *xdi;
  165.                   Printf("ArchiverName:   %s\n", ai->xai_Client->xc_ArchiverName);
  166.  
  167.                   xdi = ai->xai_DiskInfo;
  168.                   while(xdi)
  169.                   {
  170.                     LONG a;
  171.  
  172.                     if(xdi->xdi_EntryNumber != 1 || xdi->xdi_Next)
  173.                       Printf("\nEntry:          %ld\n", xdi->xdi_EntryNumber);
  174.                     Printf("EntryInfo:      %s\n", xdi->xdi_EntryInfo ? xdi->xdi_EntryInfo : "<none>");
  175.                     Printf("SectorSize:     %ld\n", xdi->xdi_SectorSize);
  176.                     Printf("Sectors:        %ld\n", xdi->xdi_TotalSectors);
  177.                     Printf("Cylinders:      %ld\n", xdi->xdi_Cylinders);
  178.                     Printf("CylSectors:     %ld\n", xdi->xdi_CylSectors);
  179.                     Printf("Heads:          %ld\n", xdi->xdi_Heads);
  180.                     Printf("TrackSectors:   %ld\n", xdi->xdi_TrackSectors);
  181.                     Printf("LowCyl:         %ld\n", xdi->xdi_LowCyl);
  182.                     Printf("HighCyl:        %ld\n", xdi->xdi_HighCyl);
  183.                     a = xdi->xdi_Flags & (XADDIF_CRYPTED|XADDIF_SECTORLABELS);
  184.                     if(a)
  185.                     {
  186.                       Printf("Flags:          ");
  187.                       if(a & XADDIF_CRYPTED)
  188.                       {
  189.                         a ^= XADDIF_CRYPTED;
  190.                         Printf("encrypted%s", a ? ", " : "\n");
  191.                       }
  192.                       if(a & XADDIF_SECTORLABELS)
  193.                       {
  194.                         a ^= XADDIF_SECTORLABELS;
  195.                         Printf("has SectorLabels%s", a ? ", " : "\n");
  196.                       }
  197.                     }
  198.                     if(xdi->xdi_TextInfo)
  199.                     {
  200.                       STRPTR a;
  201.                       struct xadTextInfo *ti;
  202.  
  203.                       for(ti = xdi->xdi_TextInfo; ti; ti = ti->xti_Next)
  204.                       {
  205.                         a = "TextInfo";
  206.                         if(ti->xti_Flags & XADTIF_BANNER)
  207.                           a = "Banner";
  208.                         else if(ti->xti_Flags & XADTIF_FILEDIZ)
  209.                           a = "DIZ-Text";
  210.  
  211.                         if(ti->xti_Size && ti->xti_Text)
  212.                           Printf("There is a %s with size %ld.\n", a, ti->xti_Size);
  213.                         else if(ti->xti_Flags & XADTIF_CRYPTED)
  214.                           Printf("There is a crypted %s.\n", a);
  215.                         else
  216.                           Printf("There is an empty %s.\n", a);
  217.                       }
  218.                       if(args.showtexts)
  219.                         ShowTexts(xdi->xdi_TextInfo);
  220.                       if(args.savetexts)
  221.                         SaveTexts(xdi->xdi_TextInfo, args.savetexts);
  222.                     }
  223.                     xdi = xdi->xdi_Next;
  224.                   }
  225.                   ret = 0;
  226.                 }
  227.                 else
  228.                 {
  229.                   struct xadDeviceInfo *dvi = 0;
  230.  
  231.                   if(args.to[strlen(args.to)-1] == ':' && stricmp(args.to, "NIL:"))
  232.                   {
  233.                     if((dvi = (struct xadDeviceInfo *)
  234.                     xadAllocObjectA(XADOBJ_DEVICEINFO, 0)))
  235.                     {
  236.                       args.to[strlen(args.to)-1] = 0; /* strip ':' */
  237.                       dvi->xdi_DOSName = args.to;
  238.                     }
  239.                     else
  240.                       err = XADERR_NOMEMORY;
  241.                   }
  242.                   if(args.showtexts || args.savetexts)
  243.                   {
  244.                     struct xadDiskInfo *xdi = ai->xai_DiskInfo;
  245.  
  246.                     while(xdi && xdi->xdi_EntryNumber < *args.entry)
  247.                       xdi = xdi->xdi_Next;
  248.                     if(xdi && xdi->xdi_TextInfo)
  249.                     {
  250.                       if(args.showtexts)
  251.                         ShowTexts(xdi->xdi_TextInfo);
  252.                       if(args.savetexts)
  253.                         SaveTexts(xdi->xdi_TextInfo, args.savetexts);
  254.                     }
  255.                   }
  256.                   if(dvi && !args.noaskinsert)
  257.                     err = AskInsertDisk(args.to);
  258.  
  259.                   if(!err && !(err = xadDiskUnArc(ai, dvi ? XAD_OUTDEVICE :
  260.                   XAD_OUTFILENAME, dvi ? (ULONG) dvi : (ULONG) args.to,
  261.                   XAD_ENTRYNUMBER, *args.entry, args.lowcyl ?
  262.                   XAD_LOWCYLINDER : TAG_IGNORE, args.lowcyl ? *args.lowcyl :
  263.                   0, args.highcyl ? XAD_HIGHCYLINDER : TAG_IGNORE,
  264.                   args.highcyl ? *args.highcyl : 0, XAD_OVERWRITE,
  265.                   args.overwrite, XAD_IGNOREGEOMETRY, args.ignoregeometry,
  266.                   XAD_FORMAT, args.format, XAD_VERIFY, TRUE, XAD_USESECTORLABELS,
  267.                   args.usesectorlabels, XAD_PROGRESSHOOK, &prhook, TAG_DONE)))
  268.                     ret = 0;
  269.                   if(dvi)
  270.                     xadFreeObjectA(dvi, 0);
  271.                 }
  272.                 xadFreeInfo(ai);
  273.               } /* xadGetInfo */
  274.               else if(err == XADERR_FILETYPE && !(ti[0].ti_Tag == XAD_INDEVICE))
  275.               {
  276.                 UBYTE r;
  277.  
  278.                 ret = 0;
  279.                 Printf("Unknown type. Press <I> to handle it as disk image: ");
  280.                 Flush(Output());
  281.                 SetMode(Input(), TRUE);
  282.                 r = FGetC(Input());
  283.                 SetMode(Input(), FALSE);
  284.                 if(r == 'i' || r == 'I')
  285.                   err = WriteDisk(&args, ti);
  286.                 else
  287.                   Printf("\n");
  288.               }
  289.  
  290.               xadFreeObjectA(ai, 0);
  291.             } /* xadAllocObject */
  292.             FreeMyTags(ti);
  293.           }
  294.         }
  295.         else
  296.           SetIoErr(ERROR_REQUIRED_ARG_MISSING);
  297.  
  298.         FreeArgs(rda);
  299.       } /* ReadArgs */
  300.  
  301.       if(SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
  302.         SetIoErr(ERROR_BREAK);
  303.  
  304.       if(err)
  305.         Printf("An error occured: %s\n", xadGetErrorText(err));
  306.       else if(ret)
  307.         PrintFault(IoErr(), 0);
  308.  
  309.       CloseLibrary((struct Library *) xadmasterbase);
  310.     } /* OpenLibrary xadmaster */
  311.     else
  312.       Printf("Could not open xadmaster.library\n");
  313.     CloseLibrary((struct Library *) dosbase);
  314.   } /* OpenLibrary dos */
  315.   return ret;
  316. }
  317.  
  318. ASM(ULONG) SAVEDS progrhook(REG(a0, struct Hook *hook),
  319. REG(a1, struct xadProgressInfo *pi))
  320. {
  321.   ULONG ret = 0;
  322.  
  323.   switch(pi->xpi_Mode)
  324.   {
  325.   case XADPMODE_ASK:
  326.     {
  327.       UBYTE r;
  328.       if(pi->xpi_Status & XADPIF_OVERWRITE)
  329.       {
  330.         Printf("\r\033[KFile already exists, overwrite? (Y|S|\033[1mN\033[0m): ");
  331.         Flush(Output());
  332.         SetMode(Input(), TRUE);
  333.         r = FGetC(Input());
  334.         if(r == 'Y' || r == 'y')
  335.           ret |= XADPIF_OVERWRITE;
  336.         else if(r == 'S' || r == 's')
  337.           ret |= XADPIF_SKIP;
  338.         SetMode(Input(), FALSE);
  339.       }
  340.       if(pi->xpi_Status & XADPIF_IGNOREGEOMETRY)
  341.       {
  342.         Printf("\r\033[KDrive geometry not correct, ignore? (Y|S|\033[1mN\033[0m): ");
  343.         Flush(Output());
  344.         SetMode(Input(), TRUE);
  345.         r = FGetC(Input());
  346.         if(r == 'Y' || r == 'y')
  347.           ret |= XADPIF_IGNOREGEOMETRY;
  348.         else if(r == 'S' || r == 's')
  349.           ret |= XADPIF_SKIP;
  350.         SetMode(Input(), FALSE);
  351.       }
  352.     }
  353.     break;
  354.   case XADPMODE_PROGRESS:
  355.     {
  356.       if(!pi->xpi_DiskInfo)
  357.         Printf("\r\033[KWrote %ld bytes", pi->xpi_CurrentSize);
  358.       else if(pi->xpi_DiskInfo->xdi_Flags & (XADDIF_NOCYLINDERS|XADDIF_NOCYLSECTORS))
  359.       {
  360.         Printf("\r\033[KWrote %ld of %ld bytes (%ld/%ld sectors)",
  361.         pi->xpi_CurrentSize, pi->xpi_DiskInfo->xdi_TotalSectors*
  362.         pi->xpi_DiskInfo->xdi_SectorSize, pi->xpi_CurrentSize/
  363.         pi->xpi_DiskInfo->xdi_SectorSize, pi->xpi_DiskInfo->xdi_TotalSectors);
  364.       }
  365.       else
  366.       {
  367.         ULONG numcyl, fullsize, curcyl, i;
  368.  
  369.         i = pi->xpi_DiskInfo->xdi_CylSectors *
  370.             pi->xpi_DiskInfo->xdi_SectorSize;
  371.         numcyl = pi->xpi_HighCyl+1-pi->xpi_LowCyl;
  372.         fullsize = numcyl * i;
  373.         curcyl = pi->xpi_CurrentSize/i;
  374.  
  375.         Printf("\r\033[KWrote %ld of %ld bytes (%ld/%ld cylinders)",
  376.         pi->xpi_CurrentSize, fullsize, curcyl, numcyl);
  377.       }
  378.       Flush(Output());
  379.     }
  380.     break;
  381.   case XADPMODE_END: 
  382.     if(pi->xpi_DiskInfo && (pi->xpi_DiskInfo->xdi_Flags & (XADDIF_NOCYLINDERS|XADDIF_NOCYLSECTORS)))
  383.       Printf("\r\033[KWrote %ld bytes (%ld sectors)\n",
  384.       pi->xpi_CurrentSize, pi->xpi_DiskInfo->xdi_TotalSectors);
  385.     else
  386.       Printf("\r\033[KWrote %ld bytes (%ld cylinders)\n",
  387.       pi->xpi_CurrentSize, pi->xpi_HighCyl+1-pi->xpi_LowCyl);
  388.     break;
  389.   case XADPMODE_ERROR: Printf("\r\033[K");
  390.     break;
  391.   }
  392.  
  393.   if(!(SetSignal(0L,0L) & SIGBREAKF_CTRL_C)) /* clear ok flag */
  394.     ret |= XADPIF_OK;
  395.  
  396.   return ret;
  397. }
  398.  
  399. static void ShowTexts(struct xadTextInfo *ti)
  400. {
  401.   ULONG i = 1, j;
  402.   BPTR fh;
  403.   STRPTR a;
  404.  
  405.   fh = Output();
  406.  
  407.   while(!(SetSignal(0L,0L) & SIGBREAKF_CTRL_C) && ti)
  408.   {
  409.     if(ti->xti_Size && ti->xti_Text)
  410.     {
  411.       Printf("»»»» TEXTINFO %ld ««««\n", i);
  412.       a = ti->xti_Text;
  413.       for(j = 0; !(SetSignal(0L,0L) & SIGBREAKF_CTRL_C) && j < ti->xti_Size; ++j)
  414.       {
  415.         if(isprint(*a) || *a == '\n' || *a == '\t' || *a == '\033')
  416.           FPutC(fh, *a);
  417.         else
  418.           FPutC(fh, '.');
  419.         ++a;
  420.       }
  421.       if(*(--a) != '\n')
  422.         FPutC(fh, '\n');
  423.     }
  424.     ti = ti->xti_Next;
  425.     ++i;
  426.   }
  427. }
  428.  
  429. static void SaveTexts(struct xadTextInfo *ti, STRPTR name)
  430. {
  431.   UBYTE namebuf[256];
  432.   ULONG i = 1;
  433.   BPTR fh;
  434.   LONG err = 0;
  435.  
  436.   while(!(SetSignal(0L,0L) & SIGBREAKF_CTRL_C) && ti && !err)
  437.   {
  438.     if(ti->xti_Size && ti->xti_Text)
  439.     {
  440.       sprintf(namebuf, "%s.%ld", name, i);
  441.       if((fh = Open(namebuf, MODE_NEWFILE)))
  442.       {
  443.         if(Write(fh, ti->xti_Text, ti->xti_Size) != ti->xti_Size)
  444.           ++err;
  445.         Close(fh);
  446.       }
  447.       else
  448.         ++err;
  449.     }
  450.     ti = ti->xti_Next;
  451.     ++i;
  452.   }
  453.   if(err)
  454.     Printf("Failed to save information texts.\n");
  455. }
  456.  
  457. static LONG WriteDisk(struct Args *args, struct TagItem *ti)
  458. {
  459.   LONG err = 0;
  460.   struct xadArchiveInfo *ai;
  461.   struct xadDeviceInfo *dvi = 0;
  462.  
  463.   if((ai = (struct xadArchiveInfo *) xadAllocObjectA(XADOBJ_ARCHIVEINFO, 0)))
  464.   {
  465.     if(args->info)
  466.     {  
  467.       if(!(err = xadGetHookAccessA(ai, ti)))
  468.       {
  469.         UBYTE r;
  470.         Printf("\r\033[KImage-Size is %ld\n", ai->xai_InSize);
  471.         xadFreeHookAccess(ai, err ? XAD_WASERROR : TAG_DONE, err, TAG_DONE);
  472.  
  473.         Printf("Test input for known filesystem? <Y>es or <N>o: ");
  474.         Flush(Output());
  475.         SetMode(Input(), TRUE);
  476.         r = FGetC(Input());
  477.         SetMode(Input(), FALSE);
  478.         if(r == 'y' || r == 'y')
  479.         {
  480.           if(!(xadGetDiskInfoA(ai, ti)))
  481.           {
  482.             Printf("\r\033[KImage-Type is '%s'\n", ai->xai_Client->xc_ArchiverName);
  483.             xadFreeInfo(ai);
  484.           }
  485.           else
  486.             Printf("\r\033[KImage-Type is unknown\n");
  487.         }
  488.         else
  489.           Printf("\n");
  490.       }
  491.     }
  492.     else
  493.     {
  494.       if(args->to[strlen(args->to)-1] == ':' && stricmp(args->to, "NIL:"))
  495.       {
  496.         if((dvi = (struct xadDeviceInfo *) xadAllocObjectA(XADOBJ_DEVICEINFO, 0)))
  497.         {
  498.           args->to[strlen(args->to)-1] = 0; /* strip ':' */
  499.           dvi->xdi_DOSName = args->to;
  500.         }
  501.         else
  502.           err = XADERR_NOMEMORY;
  503.       }
  504.  
  505.       if(dvi && !args->noaskinsert)
  506.         err = AskInsertDisk(args->to);
  507.  
  508.       if(!err)
  509.       { 
  510.         if(!(err = xadGetHookAccess(ai, XAD_OVERWRITE, args->overwrite,
  511.         XAD_IGNOREGEOMETRY, args->ignoregeometry, XAD_FORMAT, args->format, XAD_VERIFY,
  512.         TRUE, XAD_PROGRESSHOOK, &prhook, dvi ? XAD_OUTDEVICE : XAD_OUTFILENAME,
  513.         dvi ? (ULONG) dvi : (ULONG) args->to, TAG_MORE, ti)))
  514.         {
  515.           err = xadHookAccess(XADAC_COPY, ai->xai_InSize, 0, ai);
  516.           xadFreeHookAccess(ai, err ? XAD_WASERROR : TAG_DONE, err, TAG_DONE);
  517.         }
  518.         if(dvi)
  519.           xadFreeObjectA(dvi, 0);
  520.       }
  521.     }
  522.     xadFreeObjectA(ai,0);
  523.   }
  524.   else
  525.     err = XADERR_NOMEMORY;
  526.  
  527.   return err;
  528. }
  529.  
  530. static LONG AskInsertDisk(STRPTR name)
  531. {
  532.   UBYTE r;
  533.   STRPTR b;
  534.                   
  535.   for(b = name; *b; ++b)
  536.     *b = toupper(*b);
  537.  
  538.   Printf("\r\033[KInsert disk into %s: and press <ENTER> (any other key to abort): ", name);
  539.   Flush(Output());
  540.   SetMode(Input(), TRUE);
  541.   r = FGetC(Input());
  542.   SetMode(Input(), FALSE);
  543.   if(r != '\r' && r != '\n')
  544.   {
  545.     Printf("\n");
  546.     return XADERR_BREAK;
  547.   }
  548.   return 0;
  549. }
  550.  
  551. static void FreeMyTags(struct TagItem *ti)
  552. {
  553.   switch(ti[0].ti_Tag)
  554.   {
  555.   case XAD_INDEVICE:
  556.     xadFreeObjectA((APTR)ti[0].ti_Data, 0);
  557.     break;
  558.   case XAD_INSPLITTED:
  559.     {
  560.       struct xadSplitFile *sf0, *sf2;
  561.       sf0 = (struct xadSplitFile *) ti[0].ti_Data;
  562.       while(sf0)
  563.       {
  564.         sf2 = sf0; sf0 = sf0->xsf_Next;
  565.         xadFreeObjectA(sf2, 0);
  566.       }
  567.     }
  568.     break;
  569.   }
  570.  
  571.   xadFreeObjectA(ti, 0);
  572. }
  573.  
  574. static struct TagItem *GetMyTags(STRPTR name, LONG *reserr)
  575. {
  576.   struct TagItem *ti = 0;
  577.   LONG i, err = 0;
  578.  
  579.   i = strlen(name);
  580.   if(i && name[i-1] == ':') /* device input */
  581.   {
  582.     if((ti = (struct TagItem *) xadAllocVec(sizeof(struct TagItem)*2, MEMF_ANY|MEMF_CLEAR)))
  583.     {
  584.       if((ti[0].ti_Data = (ULONG) xadAllocObjectA(XADOBJ_DEVICEINFO, 0)))
  585.       {
  586.         name[i-1] = 0; /* strip ':' */
  587.         ((struct xadDeviceInfo *)ti[0].ti_Data)->xdi_DOSName = name;
  588.         ti[0].ti_Tag = XAD_INDEVICE;
  589.       }
  590.       else
  591.         err = XADERR_NOMEMORY;
  592.     }
  593.     else
  594.       err = XADERR_NOMEMORY;
  595.   }
  596.   else
  597.   {
  598.     struct AnchorPath *APath;
  599.     STRPTR s, f;
  600.     ULONG *filelist, *fl = 0, *a, *b, retval = 0, namesize = 0;
  601.  
  602.     if((APath = (struct AnchorPath *) AllocMem(sizeof(struct AnchorPath)+512, MEMF_PUBLIC|MEMF_CLEAR)))
  603.     {
  604.       APath->ap_BreakBits = SIGBREAKF_CTRL_C;
  605.       APath->ap_Strlen = 512;
  606.  
  607.       while(!retval)
  608.       {
  609.         filelist = 0;
  610.         for(retval = MatchFirst(name, APath); !retval; retval = MatchNext(APath))
  611.         {
  612.           if(APath->ap_Info.fib_DirEntryType < 0)
  613.           {
  614.             i = strlen(APath->ap_Buf)+1;
  615.             if(!(a = (ULONG *) AllocVec(i+4, MEMF_ANY)))
  616.               break;
  617.             CopyMem(APath->ap_Buf, a+1, i);
  618.             namesize += i;
  619.             if(!filelist)
  620.             {
  621.               filelist = a; *a = 0;
  622.             }
  623.             else if(stricmp((STRPTR) (filelist+1), APath->ap_Buf) >= 0)
  624.             {
  625.               *a = (ULONG) filelist; filelist = a;
  626.             }
  627.             else
  628.             {
  629.               for(b = filelist; *b && (i = SDI_stricmp((STRPTR) (*b+4),
  630.               APath->ap_Buf)) < 0; b = (ULONG *) *b)
  631.                 ;
  632.               *a = *b; *b = (ULONG) a;
  633.             }
  634.           }
  635.         }
  636.         if(fl)
  637.         {
  638.           for(b = fl; *b; b = (ULONG *) *b)
  639.             ;
  640.           *b = (ULONG) filelist;
  641.         }
  642.         else
  643.           fl = filelist;
  644.         MatchEnd(APath);
  645.         if(retval == ERROR_NO_MORE_ENTRIES)
  646.         {
  647.           retval = 0;
  648.           break;
  649.         }
  650.       }
  651.  
  652.       if(!retval)
  653.       {
  654.         i = 0;
  655.         for(b = fl; b; b = (ULONG *) *b)
  656.           ++i;
  657.         if((ti = (struct TagItem *) xadAllocVec(2*sizeof(struct TagItem)+namesize, MEMF_ANY|MEMF_CLEAR)))
  658.         {
  659.           s = ((STRPTR) ti)+(2*sizeof(struct TagItem));
  660.           if(i == 1)
  661.           {
  662.             ti[0].ti_Tag = XAD_INFILENAME;
  663.             ti[0].ti_Data = (ULONG) s;
  664.             for(f = (STRPTR) (fl+1); *f; ++f)
  665.               *(s++) = *f;
  666.             /* *s = 0; */
  667.           }
  668.           else
  669.           {
  670.             struct xadSplitFile *sf = 0, *sf2;
  671.             ti[0].ti_Tag = XAD_INSPLITTED;
  672.             for(b = fl; !err && b; b = (ULONG *) *b)
  673.             {
  674.               if((sf2 = xadAllocObjectA(XADOBJ_SPLITFILE, 0)))
  675.               {
  676.                 if(sf)
  677.                   sf->xsf_Next = sf2;
  678.                 else
  679.                   ti[0].ti_Data = (ULONG) sf2;
  680.                 sf = sf2;
  681.                 sf->xsf_Type = XAD_INFILENAME;
  682.                 sf->xsf_Data = (ULONG) s;
  683.               }
  684.               else
  685.                 err = XADERR_NOMEMORY;
  686.               for(f = (STRPTR) (b+1); *f; ++f)
  687.                 *(s++) = *f;
  688.               *(s++) = 0;
  689.             }
  690.           }
  691.         }
  692.         else
  693.           err = XADERR_NOMEMORY;
  694.       }
  695.  
  696.       while(fl)
  697.       {
  698.         a = (ULONG *) *fl;
  699.         FreeVec(fl);
  700.         fl = a;
  701.       }
  702.  
  703.       FreeMem(APath, sizeof(struct AnchorPath)+512);
  704.     }
  705.  
  706.     if(!retval)
  707.     {
  708.       if(ti[0].ti_Tag == XAD_INSPLITTED)
  709.       {
  710.         struct xadSplitFile *sf;
  711.         Printf("Loading files in following order: ");
  712.  
  713.         for(sf = (struct xadSplitFile *) ti[0].ti_Data; sf; sf=sf->xsf_Next)
  714.           Printf("%s%s", sf->xsf_Data, sf->xsf_Next ? ", " : "\n");
  715.       }
  716.     }
  717.     else
  718.       err = XADERR_INPUT;
  719.   }
  720.  
  721.   if(err)
  722.   {
  723.     *reserr = err;
  724.     if(ti)
  725.     {
  726.       FreeMyTags(ti); ti = 0;
  727.     }
  728.   }
  729.   return ti;
  730. }
  731.  
  732.